package bg.btanev.eightyfour.domain;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate;

import bg.btanev.eightyfour.domain.entitybase.DomainEntity;

/**
 *
 * @author B.Tanev
 *
 */
public class Tag extends DomainEntity<String> {
	/**
	 *
	 */
	private static final long serialVersionUID = -7778839724741613263L;

	public static final int MIN_TAG_LENGTH = 3;

	private static ThreadLocal<Map<String, Tag>> threadCache = new ThreadLocal<Map<String, Tag>>();

	protected Tag() {
		super();
	}

	public static Tag createTag(String name) {
		name = validateAndNormalizeName(name);
		Map<String, Tag> map = getCacheMap();
		Tag tag = map.get(name);
		if (tag == null) {
			map.put(name, tag = new Tag(name));
		}

		return tag;
	}

	public static void clearLocalTagsCache() {
		getCacheMap().clear();
	}

	private static Map<String, Tag> getCacheMap() {
		Map<String, Tag> map = threadCache.get();
		if (map == null) {
			map = new HashMap<String, Tag>();
			threadCache.set(map);
		}
		return map;
	}

	public Tag(String name) {
		this();

		name = validateAndNormalizeName(name);
		setId(name);
	}

	public static String validateAndNormalizeName(String name) {
		Validate.notEmpty(name, "Tag name cannot be empty.");

		name = StringUtils.trimToNull(StringUtils.lowerCase(name));
		if (name == null) {
			throw new IllegalArgumentException(
					"Invalid 'name' parameter value. There must remain a characters value after the string was trimmed.");
		}
		if (name.length() < MIN_TAG_LENGTH) {
			throw new IllegalArgumentException("Invalid 'name' parameter value. Value must have at leasted "
					+ MIN_TAG_LENGTH + " visual characters");
		}
		return name;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Tag other = (Tag) obj;
		if (getId() == null) {
			if (other.getId() != null)
				return false;
		} else if (!getId().equals(other.getId()))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "Tag [toString()=" + super.toString() + "]";
	}
}
